package com.tepth.remote.core.net.retrofit;

import android.content.Context;

import com.alibaba.fastjson.JSONObject;
import com.tepth.remote.core.net.CommonParams;
import com.tepth.remote.core.net.HttpMethod;
import com.tepth.remote.core.net.callback.IError;
import com.tepth.remote.core.net.callback.ISuccess;
import com.tepth.remote.core.net.loader.ControlLoader;
import com.tepth.remote.core.net.loader.LoaderStyle;

import java.io.File;
import java.util.WeakHashMap;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

/**
 * Description:Retrofit连接工具类
 *
 * @author Hequn.Lee
 * @date 2018/11/8
 */
@SuppressWarnings("all")
public class RxRetrofitClient {

    /**
     * 请求的相对地址
     */
    private final String URL;
    /**
     * 请求参数集合
     */
    private final WeakHashMap<String, Object> PARAMS;
    /**
     * 请求体
     */
    private final RequestBody BODY;
    /**
     * 要上传的文件
     */
    private final File FILE;
    /**
     * 上下文
     */
    private final Context CONTEXT;
    /**
     * 菊花样式
     */
    private final LoaderStyle LOADERSTYLE;
    /**
     * 成功回调接口
     */
    private final ISuccess SUCCESS;
    /**
     * 失败回调接口
     */
    private final IError ERROR;

    RxRetrofitClient(String url,
                     WeakHashMap<String, Object> params,
                     RequestBody body,
                     File file,
                     Context context,
                     LoaderStyle loaderStyle,
                     ISuccess success,
                     IError error) {
        this.URL = url;
        this.PARAMS = params;
        this.BODY = body;
        this.FILE = file;
        this.CONTEXT = context;
        this.LOADERSTYLE = loaderStyle;
        this.SUCCESS = success;
        this.ERROR = error;
    }

    /**
     * 创建Retrofit连接构造类
     *
     * @return Retrofit连接构造类
     */
    public static RxRetrofitClientBuilder builder() {
        return new RxRetrofitClientBuilder();
    }

    /**
     * Request请求
     *
     * @param method 请求的枚举类型
     */
    private Observable<String> request(HttpMethod method) {
        final RxRetrofitService service = RetrofitCreator.getRxRetrofitService();
        Observable<String> observable = null;
        if (LOADERSTYLE != null && CONTEXT != null) {
            ControlLoader.showLoading(CONTEXT, LOADERSTYLE);
        }
        switch (method) {
            case GET:
                observable = service.get(URL, PARAMS);
                break;
            case POST:
                observable = service.post(URL, PARAMS);
                break;
            case POST_RAW:
                observable = service.postRaw(URL, BODY);
                break;
            case PUT:
                observable = service.put(URL, PARAMS);
                break;
            case PUT_RAW:
                observable = service.putRaw(URL, BODY);
                break;
            case DELETE:
                observable = service.delete(URL, PARAMS);
                break;
            case UPLOAD:
                final RequestBody requestBody =
                        RequestBody.create(MediaType.parse(MultipartBody.FORM.toString()), FILE);
                final MultipartBody.Part body =
                        MultipartBody.Part.createFormData("file", FILE.getName(), requestBody);
                observable = service.upload(URL, body);
                break;
            default:
                break;
        }
        return observable;
    }

    public final Disposable get() {
        return request(HttpMethod.GET)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull final String response) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        JSONObject jsonObject = JSONObject.parseObject(response);
                        int resultCode = jsonObject.getInteger("Code");
                        JSONObject resultValue = jsonObject.getJSONObject("Value");
                        String resultText = jsonObject.getString("Text");
                        if (CommonParams.SUCCESS_CODE_NORMAL == resultCode) {
                            if (SUCCESS != null) {
                                SUCCESS.onSuccess(resultValue);
                            }
                        } else {
                            if (ERROR != null) {
                                ERROR.onError(resultCode, resultText);
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        if (ERROR != null) {
                            String msg = throwable.getMessage();
                            ERROR.onError(1001, msg);
                        }
                    }
                });
    }

    public final Disposable getOriginal() {
        return request(HttpMethod.GET)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull final String response) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        if (SUCCESS != null) {
                            SUCCESS.onSuccess(response);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        if (ERROR != null) {
                            String msg = throwable.getMessage();
                            ERROR.onError(1001, msg);
                        }
                    }
                });
    }

    public final Disposable post() {
        return request(HttpMethod.GET)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull final String response) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        JSONObject jsonObject = JSONObject.parseObject(response);
                        int resultCode = jsonObject.getInteger("Code");
                        JSONObject resultValue = jsonObject.getJSONObject("Value");
                        String resultText = jsonObject.getString("Text");
                        if (CommonParams.SUCCESS_CODE_NORMAL == resultCode) {
                            if (SUCCESS != null) {
                                SUCCESS.onSuccess(resultValue);
                            }
                        } else {

                            if (ERROR != null) {
                                ERROR.onError(resultCode, resultText);
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        if (LOADERSTYLE != null && CONTEXT != null) {
                            ControlLoader.closeLoading();
                        }
                        if (ERROR != null) {
                            String msg = throwable.getMessage();
                            ERROR.onError(1001, msg);
                        }
                    }
                });
    }

    public final Observable<String> put() {
        //采用的是传参的POST请求
        if (BODY == null) {
            return request(HttpMethod.PUT);
        } else {
            if (!PARAMS.isEmpty()) {
                throw new RuntimeException("params must be null");
            }
            return request(HttpMethod.PUT_RAW);
        }
    }

    public final Observable<String> delete() {
        return request(HttpMethod.DELETE);
    }

    public final Observable<ResponseBody> download() {
        return RetrofitCreator.getRxRetrofitService().download(URL, PARAMS);
    }
}
